
package ogame.utilities.ships;

import ogame.utilities.Constants;
import ogame.utilities.research.Research;
import ogame.utilities.research.ResearchType;

/**
 *
 * @author scchang
 */
public class Ship {
    
    public static enum DriveBase{
        COMBUSTION, IMPULSE, HYPERSPACE
    };

    public final static Ship SMALL_CARGO = new SmallCargo("Small Cargo", 10000, 20, 4000,
            10, 5, 5000,
            2000, 2000, 0,
            DriveBase.COMBUSTION);
    public final static Ship LARGE_CARGO = new Ship("Large Cargo", 7500, 50, 12000,
            25, 5, 25000,
            6000, 6000, 0,
            DriveBase.COMBUSTION);
    public final static Ship LIGHT_FIGHTER = new Ship("Light Fighter", 12500, 20, 4000,
            10, 50, 50,
            3000, 1000, 0,
            DriveBase.COMBUSTION);
    public final static Ship HEAVY_FIGHTER = new Ship("Heavy Fighter", 10000, 75, 10000,
            25, 150, 100,
            6000, 4000, 0,
            DriveBase.IMPULSE);
    public final static Ship CRUISER = new Ship("Cruiser", 15000, 300, 27000,
            50, 400, 800,
            20000, 7000, 2000,
            DriveBase.IMPULSE);
    public final static Ship BATTLESHIP = new Ship("Battleship", 10000, 500, 60000,
            200, 1000, 1500,
            45000, 15000, 0,
            DriveBase.HYPERSPACE);
    public final static Ship BATTLECRUISER = new Ship("Battlecruiser", 10000, 250, 70000,
            400, 700, 750,
            30000, 40000, 15000,
            DriveBase.HYPERSPACE);
    public final static Ship DESTROYER = new Ship("Destroyer", 5000, 1000, 110000,
            500, 2000, 2000,
            60000, 50000, 15000,
            DriveBase.HYPERSPACE);
    public final static Ship DEATHSTAR = new Ship("Deathstar", 100, 1, 9000000,
            50000, 200000, 1000000,
            5000000, 4000000, 1000000,
            DriveBase.HYPERSPACE);
    public final static Ship BOMBER = new Bomber("Bomber", 5000, 1000, 75000,
            500, 1000, 500,
            50000, 25000, 15000,
            DriveBase.HYPERSPACE);
    public final static Ship RECYCLER = new Ship("Recycler", 2000, 300, 16000,
            10, 1, 20000,
            10000, 6000, 2000,
            DriveBase.COMBUSTION);
    public final static Ship ESPIONAGE_PROBE = new Ship("Espionage probe", 100000000, 1, 1000,
            0.01, 0.01, 5,
            0, 1000, 0,
            DriveBase.COMBUSTION);
    public final static Ship SOLAR_SATELLITE = new Ship("Solar Satellite", 0, 0, 2000,
            1, 1, 0,
            0, 2000, 500,
            DriveBase.COMBUSTION);
    public final static Ship COLONY_SHIP = new Ship("Colony Ship", 2500, 1000, 30000,
            100, 50, 7500,
            10000, 20000, 10000,
            DriveBase.IMPULSE);
    public final static Ship INTERPLANETARY_MISSILES = new Ship("Interplanetary Missiles", 0, 0, 0,
            0, 0, 0,
            12500, 2500, 10000,
            DriveBase.IMPULSE);
    
    public static Ship[] ships = {SMALL_CARGO, LARGE_CARGO, LIGHT_FIGHTER,
        HEAVY_FIGHTER, CRUISER, BATTLESHIP, BATTLECRUISER, DESTROYER, DEATHSTAR,
        BOMBER, RECYCLER, ESPIONAGE_PROBE, SOLAR_SATELLITE, COLONY_SHIP,
        INTERPLANETARY_MISSILES};
    
    public static Ship enum2Ship(ShipType shipType){
        for(Ship ship: ships){
            if(ship.toString().toUpperCase().replace(' ', '_').
                    equals(shipType.name())){
                return ship;
            }
        }
        return null;
    }
    
    public static ShipType ship2Enum(Ship ship){
        for(ShipType type: ShipType.values()){
            if(ship.toString().toUpperCase().replace(' ' , '_')
                    .equals(type.name())){
                return type;
            }
        }
        return null;
    }
    
    
    protected String name;
    protected double speed;
    protected double fuel_consumption;
    protected double structural_integrity;
    protected double shield;
    protected double weapon;
    protected double cargo;
    protected double metal;
    protected double deut;
    protected double crystal;
    protected DriveBase driveBase;
    
    protected Ship(String name, double speed, double fuel, double struct,
            double shield, double weapon, double cargo,
            double metal, double crystal, double deut,
            DriveBase driveBase){
        this.name = name;
        this.speed = speed;
        this.fuel_consumption = fuel;
        this.structural_integrity = struct;
        this.shield = shield;
        this.weapon = weapon;
        this.cargo = cargo;
        this.metal = metal;
        this.deut = deut;
        this.crystal = crystal;
        this.driveBase = driveBase;
    }

    /**
     * @return the name
     */
    public String getName() {
        return name;
    }

    /**
     * @return the speed
     */
    public double getSpeed(Research research) {
        if(this.driveBase == DriveBase.COMBUSTION){
            return this.speed * (1+research.get(ResearchType.COMBUSTION_DRIVE)
                    * Constants.COMBUSTION_DRIVE_BONUS);
        }else if(this.driveBase == DriveBase.IMPULSE){
            return this.speed * (1+research.get(ResearchType.IMPULSE_DRIVE)
                    * Constants.IMPULSE_DRIVE_BONUS);
        }else if(this.driveBase == DriveBase.HYPERSPACE){
            return this.speed * (1+research.get(ResearchType.HYPERSPACE_DRIVE)
                    * Constants.HYPERSPACE_DRIVE_BONUS);
        }else{
            throw new IllegalStateException("In ship:getspeed, unable to switch on drivebase.");
        }
    }

    /**
     * @return the fuel_consumption
     */
    public double getFuel_consumption() {
        return fuel_consumption;
    }

    /**
     * @return the structural_integrity
     */
    public double getStructural_integrity() {
        return structural_integrity;
    }

    /**
     * @return the shield
     */
    public double getShield() {
        return shield;
    }

    /**
     * @return the weapon
     */
    public double getWeapon() {
        return weapon;
    }

    /**
     * @return the cargo
     */
    public double getCargo() {
        return cargo;
    }

    /**
     * @return the metal
     */
    public double getMetal() {
        return metal;
    }


    /**
     * @return the deut
     */
    public double getDeut() {
        return deut;
    }


    /**
     * @return the crystal
     */
    public double getCrystal() {
        return crystal;
    }
    
    public String toString(){
        return this.name;
    }
    
    public double computeSingleConsumption(Research research, double duration, double distance){
        double speed = 3500/(duration-10)*Math.sqrt((distance * 10)/this.getSpeed(research));
        return (this.getFuel_consumption()*distance/35000*Math.pow(speed + 1, 2));
    }

}
